{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用MindSpore实现简单线性函数拟合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 概述\n",
    "\n",
    "回归问题算法通常是利用一系列属性来预测一个值，预测的值是连续的。例如给出一套房子的一些特征数据，如面积、卧室数等等来预测房价，利用最近一周的气温变化和卫星云图来预测未来的气温情况等。如果一套房子实际价格为500万元，通过回归分析的预测值为499万元，则认为这是一个比较好的回归分析。在机器学习问题中，常见的回归分析有线性回归、多项式回归、逻辑回归等。本例子介绍线性回归算法，并通过MindSpore进行线性回归AI训练体验。\n",
    "\n",
    "整体流程如下：\n",
    "\n",
    "1. 生成数据集\n",
    "2. 定义训练网络\n",
    "3. 定义前向传播网络与反向传播网络并关联\n",
    "4. 拟合过程可视化准备\n",
    "5. 执行训练"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 环境准备\n",
    "\n",
    "设置MindSpore运行配置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.002170Z",
     "start_time": "2020-09-14T10:38:39.441746Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore import context\n",
    "\n",
    "context.set_context(mode=context.GRAPH_MODE, device_target=\"CPU\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`GRAPH_MODE`：图模式。\n",
    "\n",
    "`device_target`：设置MindSpore的训练硬件为CPU。\n",
    "\n",
    "> 本教程代码依赖`matplotlib`第三方支持包，可使用命令`pip install matplotlib`安装。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 生成数据集\n",
    "\n",
    "### 定义数据集生成函数\n",
    "\n",
    "`get_data`用于生成训练数据集和测试数据集。由于拟合的是线性数据，假定要拟合的目标函数为：$f(x)=2x+3$，那么我们需要的训练数据集应随机分布于函数周边，这里采用了$f(x)=2x+3+noise$的方式生成，其中`noise`为遵循标准正态分布规律的随机数值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.007850Z",
     "start_time": "2020-09-14T10:38:40.003169Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "def get_data(num, w=2.0, b=3.0):\n",
    "    for i in range(num):\n",
    "        x = np.random.uniform(-10.0, 10.0)\n",
    "        noise = np.random.normal(0, 1)\n",
    "        y = x * w + b + noise\n",
    "        yield np.array([x]).astype(np.float32), np.array([y]).astype(np.float32)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用`get_data`生成50组测试数据，并可视化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.355635Z",
     "start_time": "2020-09-14T10:38:40.009930Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "eval_data = list(get_data(50))\n",
    "x_target_label = np.array([-10, 10, 0.1])\n",
    "y_target_label = x_target_label * 2 + 3\n",
    "x_eval_label,y_eval_label = zip(*eval_data)\n",
    "\n",
    "plt.scatter(x_eval_label, y_eval_label, color=\"red\", s=5)\n",
    "plt.plot(x_target_label, y_target_label, color=\"green\")\n",
    "plt.title(\"Eval data\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上图中绿色线条部分为目标函数，红点部分为验证数据`eval_data`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义数据增强函数\n",
    "\n",
    "使用MindSpore的数据增强函数，将数据进行增强操作，操作解释如下：\n",
    "\n",
    "- `ds.GeneratorDataset`：将生成的数据转换为MindSpore的数据集，并且将生成的数据的x，y值存入到`data`和`label`的数组中。\n",
    "- `batch`：将`batch_size`个数据组合成一个batch。\n",
    "- `repeat`：将数据集数量倍增。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.390782Z",
     "start_time": "2020-09-14T10:38:40.356644Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore import dataset as ds\n",
    "\n",
    "def create_dataset(num_data, batch_size=16, repeat_size=1):\n",
    "    input_data = ds.GeneratorDataset(list(get_data(num_data)), column_names=['data','label'])\n",
    "    input_data = input_data.batch(batch_size)\n",
    "    input_data = input_data.repeat(repeat_size)\n",
    "    return input_data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "使用数据集增强函数生成训练数据，并查看训练数据的格式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.435708Z",
     "start_time": "2020-09-14T10:38:40.391790Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The dataset size of ds_train: 100\n",
      "dict_keys(['data', 'label'])\n",
      "The x label value shape: (16, 1)\n",
      "The y label value shape: (16, 1)\n"
     ]
    }
   ],
   "source": [
    "num_data = 1600\n",
    "batch_size = 16\n",
    "repeat_size = 1\n",
    "\n",
    "ds_train = create_dataset(num_data, batch_size=batch_size, repeat_size=repeat_size) \n",
    "print(\"The dataset size of ds_train:\", ds_train.get_dataset_size())\n",
    "dict_datasets = ds_train.create_dict_iterator().get_next()\n",
    "\n",
    "print(dict_datasets.keys())\n",
    "print(\"The x label value shape:\", dict_datasets[\"data\"].shape)\n",
    "print(\"The y label value shape:\", dict_datasets[\"label\"].shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过定义的`create_dataset`将生成的1600个数据增强为了100组shape为16x1的数据集。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义训练网络\n",
    "\n",
    "在MindSpore中使用`nn.Dense`生成单个数据输入，单个数据输出的线性函数模型：\n",
    "\n",
    "$$f(x)=wx+b\\tag{1}$$\n",
    "\n",
    "并使用Normal算子随机初始化权重$w$和$b$。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.441532Z",
     "start_time": "2020-09-14T10:38:40.436780Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore.common.initializer import Normal\n",
    "from mindspore import nn\n",
    "\n",
    "class LinearNet(nn.Cell):\n",
    "    def __init__(self):\n",
    "        super(LinearNet, self).__init__()\n",
    "        self.fc = nn.Dense(1, 1, Normal(0.02), Normal(0.02))\n",
    "        \n",
    "    def construct(self, x):\n",
    "        x = self.fc(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "调用网络查看初始化的模型参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.456400Z",
     "start_time": "2020-09-14T10:38:40.442544Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Parameter (name=fc.weight, value=Tensor(shape=[1, 1], dtype=Float32,\n",
      "[[3.68014202e-002]])), Parameter (name=fc.bias, value=Tensor(shape=[1], dtype=Float32, [3.68014202e-002]))]\n"
     ]
    }
   ],
   "source": [
    "net = LinearNet()\n",
    "model_params = net.trainable_params()\n",
    "print(model_params)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "初始化网络模型后，接下来将初始化的网络函数和训练数据集进行可视化，了解拟合前的模型函数情况。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.607733Z",
     "start_time": "2020-09-14T10:38:40.457985Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mindspore import Tensor\n",
    "\n",
    "x_model_label = np.array([-10, 10, 0.1])\n",
    "y_model_label = (x_model_label * Tensor(model_params[0]).asnumpy()[0][0] + \n",
    "                 Tensor(model_params[1]).asnumpy()[0])\n",
    "\n",
    "plt.axis([-10, 10, -20, 25])\n",
    "plt.scatter(x_eval_label, y_eval_label, color=\"red\", s=5)\n",
    "plt.plot(x_model_label, y_model_label, color=\"blue\")\n",
    "plt.plot(x_target_label, y_target_label, color=\"green\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从上图中可以看出，蓝色线条的初始化模型函数与绿色线条的目标函数还是有较大的差别的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义前向传播网络与反向传播网络并关联"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来需要定义模型的损失函数，这里采用均方差的方法用于判断拟合的效果如何，即均方差值越小，拟合的效果越好，其损失损失函数公式为：\n",
    "\n",
    "$$J(w)=\\frac{1}{2m}\\sum_{i=1}^m(h(x_i)-y^{(i)})^2\\tag{2}$$\n",
    "\n",
    "假设训练数据第$i$个数据为$(x_i,y^{(i)})$，公式2中的参数解释如下：\n",
    "\n",
    "- $J(w)$为损失值。\n",
    "\n",
    "- $m$为样本数据的数量，本例中$m$的值为`batch_size`。\n",
    "\n",
    "- $h(x_i)$为第$i$个数据的$x_i$值代入模型网络（公式1）后的预测值。\n",
    "\n",
    "- $y^{(i)}$为第$i$个数据中的$y^{(i)}$值（label值）。\n",
    "\n",
    "### 定义前向传播网络\n",
    "\n",
    "前向传播网络包含两个部分，其中：\n",
    "\n",
    "1. 将参数带入到模型网络中得出预测值。\n",
    "2. 使用预测值和训练数据计算出loss值。\n",
    "\n",
    "在MindSpore中使用如下方式实现。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.615390Z",
     "start_time": "2020-09-14T10:38:40.609289Z"
    }
   },
   "outputs": [],
   "source": [
    "net = LinearNet()\n",
    "net_loss = nn.loss.MSELoss()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义反向传播网络\n",
    "\n",
    "反向传播网络的目标是不断变换权重值，使得loss值取得最小值，一般的在线性网络中采用权重更新公式：\n",
    "\n",
    "$$w_{t}=w_{t-1}-\\alpha\\frac{\\partial{J(w_{t-1})}}{\\partial{w}}\\tag{3}$$\n",
    "\n",
    "公式3参数解释：\n",
    "\n",
    "- $w_{t}$为迭代后的权重值。\n",
    "- $w_{t-1}$为迭代前的权重值。\n",
    "- $\\alpha$为学习率。\n",
    "- $\\frac{\\partial{J(w_{t-1}\\ )}}{\\partial{w}}$为损失函数对权重$w_{t-1}$的微分。\n",
    "\n",
    "函数中所有的权重值更新完成后，将值传入到模型函数中，这个过程就是反向传播过程，实现此过程需要使用MindSpore中的优化器函数，如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.629217Z",
     "start_time": "2020-09-14T10:38:40.616392Z"
    }
   },
   "outputs": [],
   "source": [
    "opt = nn.Momentum(net.trainable_params(), learning_rate=0.005, momentum=0.9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 关联前向和反向传播网络\n",
    "\n",
    "定义完成前向传播和反向传播后，在MindSpore中需要调用`Model`函数，将前面定义的网络，损失函数，优化器函数关联起来，使之变成完整的计算网络。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.645718Z",
     "start_time": "2020-09-14T10:38:40.630789Z"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore.train import Model\n",
    "\n",
    "model = Model(net, net_loss, opt)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 拟合过程可视化准备\n",
    "\n",
    "### 定义绘图函数\n",
    "\n",
    "为了使得整个训练过程更容易理解，需要将训练过程的测试数据、目标函数和模型网络进行可视化，这里定义了可视化函数，将在每个step训练结束后调用，展示模型网络的拟合过程。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.680586Z",
     "start_time": "2020-09-14T10:38:40.646738Z"
    }
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import time\n",
    "\n",
    "def plot_model_and_datasets(net, eval_data):\n",
    "    weight = net.trainable_params()[0]\n",
    "    bias = net.trainable_params()[1]\n",
    "    x = np.arange(-10, 10, 0.1)\n",
    "    y = x * Tensor(weight).asnumpy()[0][0] + Tensor(bias).asnumpy()[0]\n",
    "    x1, y1 = zip(*eval_data)\n",
    "    x_target = x\n",
    "    y_target = x_target * 2 + 3\n",
    "    \n",
    "    plt.axis([-11, 11, -20, 25])\n",
    "    plt.scatter(x1, y1, color=\"red\", s=5)\n",
    "    plt.plot(x, y, color=\"blue\")\n",
    "    plt.plot(x_target, y_target, color=\"green\")\n",
    "    plt.show()\n",
    "    time.sleep(0.2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 定义回调函数\n",
    "\n",
    "MindSpore提供的工具，可对模型训练过程进行自定义控制，这里在`step_end`中调用可视化函数，展示拟合过程。更多的使用可参考[官网说明](https://www.mindspore.cn/tutorial/training/zh-CN/master/advanced_use/custom_debugging_info.html#callback)\n",
    "\n",
    "- `display.clear_output`：清除打印内容，实现动态拟合效果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:38:40.706063Z",
     "start_time": "2020-09-14T10:38:40.681635Z"
    }
   },
   "outputs": [],
   "source": [
    "from IPython import display\n",
    "from mindspore.train.callback import Callback\n",
    "\n",
    "class ImageShowCallback(Callback):\n",
    "    def __init__(self, net, eval_data):\n",
    "        self.net = net\n",
    "        self.eval_data = eval_data\n",
    "        \n",
    "    def step_end(self, run_context):\n",
    "        plot_model_and_datasets(self.net, self.eval_data)\n",
    "        display.clear_output(wait=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 执行训练\n",
    "\n",
    "完成以上过程后，可以使用训练数`ds_train`对模型训练，这里调用`model.train`进行，其中参数解释：\n",
    "\n",
    "- `epoch`：训练迭代的整个数据集的次数。\n",
    "- `ds_train`：训练数据集。\n",
    "- `callbacks`：训练过程中需要调用的回调函数。\n",
    "- `dataset_sink_model`：数据集下沉模式，支持Ascend、GPU计算平台，本例为CPU计算平台设置为False。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T10:47:22.917679Z",
     "start_time": "2020-09-14T10:38:40.707096Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parameter (name=fc.weight, value=[[2.0405223]]) \n",
      "Parameter (name=fc.bias, value=[2.9574146])\n"
     ]
    }
   ],
   "source": [
    "\n",
    "from mindspore.train.callback import LossMonitor\n",
    "\n",
    "epoch = 1\n",
    "imageshow_cb = ImageShowCallback(net, eval_data)\n",
    "model.train(epoch, ds_train, callbacks=[imageshow_cb], dataset_sink_mode=False)\n",
    "\n",
    "plot_model_and_datasets(net,eval_data)\n",
    "print(net.trainable_params()[0], \"\\n%s\" % net.trainable_params()[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-14T04:00:18.787349Z",
     "start_time": "2020-09-14T04:00:18.784236Z"
    }
   },
   "source": [
    "训练完成后打印出最终模型的权重参数，其中weight接近于2.0，bias接近于3.0，模型训练完成，符合预期。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "本次体验我们了解了线性拟合的算法原理，并在MindSpore框架下实现了相应的算法定义，了解了线性拟合这类的线性回归模型在MindSpore中的训练过程，并最终拟合出了一条接近目标函数的模型函数。另外有兴趣的可以调整数据集的生成区间从（-10,10）扩展到（-100,100），看看权重值是否更接近目标函数；调整学习率大小，看看拟合的效率是否有变化；当然也可以探索如何使用MindSpore拟合$f(x)=ax^2+bx+c$这类的二次函数或者更高次的函数。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
